package com.yami.shop.cp.comment.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yami.shop.bean.enums.SendType;
import com.yami.shop.bean.model.NotifyTemplate;
import com.yami.shop.bean.model.SmsLog;
import com.yami.shop.common.bean.ALiDaYu;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.Json;
import com.yami.shop.config.ShopConfig;
import com.yami.shop.cp.comment.dao.UserSubmitPersonMapper;
import com.yami.shop.cp.comment.model.UserSubmitPerson;
import com.yami.shop.cp.comment.service.UserSubmitPersonService;
import com.yami.shop.dao.SmsLogMapper;
import com.yami.shop.service.NotifyTemplateService;
import com.yami.shop.service.UserService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author xch
 * @since 2021-06-24
 */
@Service
@AllArgsConstructor
public class UserSubmitPersonServiceImpl extends ServiceImpl<UserSubmitPersonMapper, UserSubmitPerson> implements UserSubmitPersonService {

    private SmsLogMapper smsLogMapper;

    private ShopConfig shopConfig;
    private final NotifyTemplateService notifyTemplateService;
    private final UserSubmitPersonMapper userSubmitPersonMapper;
    /**
     * 产品域名,开发者无需替换
     */
    private static final String DOMAIN = "dysmsapi.aliyuncs.com";
    /**
     * 产品RegionId,开发者无需替换
     */
    private static final String REGION_ID = "cn-hangzhou";

    /**
     * 产品version,开发者无需替换
     */
    private static final String VERSION = "2017-05-25";

    /**
     * 产品Action,开发者无需替换
     */
    private static final String ACTION = "SendSms";

    /**
     * 当天最大验证码短信发送量
     */
    private static final int TODAY_MAX_SEND_VALID_SMS_NUMBER = 10;

    /**
     * 一段时间内短信验证码的最大验证次数
     */
    private static final int TIMES_CHECK_VALID_CODE_NUM = 10;

    /**
     * 短信验证码的前缀
     */
    private static final String CHECK_VALID_CODE_NUM_PREFIX = "checkValidCodeNum_";

    /**
     * 短信列表的大小/列表的索引
     */
    private static final Integer INDEX = 0;



    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void sendSubmitPersonLoginCode(SendType sendType, String mobile, HashMap<String, String> params) {
        UserSubmitPerson userSubmitPerson = userSubmitPersonMapper.selectOne(new LambdaQueryWrapper<UserSubmitPerson>()
                .eq(UserSubmitPerson::getMobile, mobile));
        if (Objects.isNull(userSubmitPerson)) {
            // 用户不存在
            throw new YamiShopBindException("yami.user.account.no.exist");
        }
        List<SmsLog> smsLogList = smsLogMapper.selectList(new LambdaQueryWrapper<SmsLog>()
                .gt(SmsLog::getRecDate, DateUtil.beginOfDay(new Date()))
                .lt(SmsLog::getRecDate, DateUtil.endOfDay(new Date()))
                .eq(SmsLog::getUserId, mobile)
                .eq(SmsLog::getType, sendType.getValue())
                .orderByDesc(SmsLog::getRecDate)
        );
        if (smsLogList.size() >= TODAY_MAX_SEND_VALID_SMS_NUMBER) {
            // 今日发送短信验证码次数已达到上限
            throw new YamiShopBindException("yami.verification.limit");
        }
        if (smsLogList.size() > INDEX) {
            SmsLog smsLogLast = smsLogList.get(INDEX);
            long currentTimeMillis = System.currentTimeMillis();
            long timeDb = DateUtil.offsetSecond(smsLogLast.getRecDate(), 60).getTime();
            if (currentTimeMillis < timeDb) {
                // 一分钟内只能发送一次验证码
                throw new YamiShopBindException("yami.verification.time.check");
            }
        }
        // 将上一条验证码失效
        smsLogMapper.invalidSmsByMobileAndType(mobile, sendType.getValue());
        String code = RandomUtil.randomNumbers(6);
        params.put("code", code);
        SmsLog smsLog = new SmsLog();
        NotifyTemplate notifyTemplate = notifyTemplateService.getOne(new LambdaQueryWrapper<NotifyTemplate>().eq(NotifyTemplate::getSendType, sendType.getValue()));
        smsLog.setType(sendType.getValue());
        smsLog.setMobileCode(params.get("code"));
        smsLog.setRecDate(new Date());
        smsLog.setStatus(1);
        smsLog.setUserId(mobile);
        smsLog.setUserPhone(mobile);
        smsLog.setContent(formatContent(notifyTemplate.getMessage(), params));
        smsLogMapper.insert(smsLog);
        Boolean flag = this.sendSms(mobile, notifyTemplate.getTemplateCode(), params);
        if(!flag){
            // 发送短信失败，请稍后再试
            throw new YamiShopBindException("yami.sending.message.failed");
        }

    }


    private String formatContent(String content, Map<String, String> params) {
        for (Map.Entry<String, String> element : params.entrySet()) {
            content = content.replace("${" + element.getKey() + "}", element.getValue());
        }
        return content;
    }

    private Boolean sendSms(String mobile, String templateCode, Map<String, String> params) {
        ALiDaYu aLiDaYu = shopConfig.getAliDaYu();

        //初始化acsClient,暂不支持region化
        IClientProfile profile = DefaultProfile.getProfile(REGION_ID, aLiDaYu.getAccessKeyId(), aLiDaYu.getAccessKeySecret());
        IAcsClient acsClient = new DefaultAcsClient(profile);

        //组装请求对象-具体描述见控制台-文档部分内容

        CommonRequest request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        request.setSysDomain(DOMAIN);
        request.setSysVersion(VERSION);
        request.setSysAction(ACTION);
        request.putQueryParameter("RegionId", REGION_ID);
        //必填:待发送手机号
        request.putQueryParameter("PhoneNumbers", mobile);
        //必填:短信签名-可在短信控制台中找到
        request.putQueryParameter("SignName", aLiDaYu.getSignName());
        //必填:短信模板-可在短信控制台中找到
        request.putQueryParameter("TemplateCode", templateCode);
        request.putQueryParameter("TemplateParam", Json.toJsonString(params));

        try {
            CommonResponse response = acsClient.getCommonResponse(request);
            System.out.println(response.getData());
            return true;
        } catch (ClientException e) {
            log.error("发送短信失败，请稍后再试：" + e.getMessage());
            return false;
        }
    }
}
